
#include <stdatomic.h>
#include <sys/types.h>
#include <unistd.h>
#include "queue.c"

typedef struct __lock_t {
	// guard 是 lock 和 unlock 过程的一个自旋锁
	atomic_flag guard;
	// 用于标记当前锁是否被一个线程获取
	// 0 表示当前还没有线程获取这把锁
	// 1 表示当前已经有一个线程获取这把锁了
	int flag;
	// 如果 flag == 1，那么再来获取这把锁的线程
	// 将在这个等待队列中阻塞、等待
	queue_t *wait_queue;
} lock_t;

void init(lock_t *mutex) {
	mutex->flag = 0;
	queue_init(mutex->wait_queue);
}

void lock(lock_t *mutex) {
	while (atomic_flag_test_and_set(&mutex->guard))
    ; // spin

	if (mutex->flag == 0) {
		mutex->flag = 1;
		atomic_flag_clear(&mutex->guard);
	} else {
		// 将当前线程 pid 放入到队列中
		queue_add(mutex->queue, gettid());
		atomic_flag_clear(&mutex->guard);
		// 伪代码，阻塞当前线程，需要发起一次系统调用
		park();
	}
}

void unlock(lock_t *mutex) {
	while (atomic_flag_test_and_set(&mutex->guard))
    ; // spin

	if (queue_empty(mutex->wait_queue)) {
		mutex->flag = 0;
	} else {
		// 伪代码，唤醒队列中队头的线程，需要发起系统调用
		unpark(queue_remove(mutex->wait_queue));
		// flag 值本来就是 1，这里加不加没关系
		mutex->flag = 1;
	}

	atomic_flag_clear(&mutex->guard);
}




